Python编程实现ID3算法,基于西瓜数据集生成决策树并评估了其好坏。
相关源码托管于Github:PnYuan/Machine-Learning_ZhouZhihua,欢迎访问。
问题回顾
这里采用了自己编程实现和调用sklearn库函数两种不同的方式,详细解答和编码过程如下:(查看完整代码):
解答内容
数据预分析
这里由数据表生成.csv文件(注意中文字符的编码格式)。采用pandas.read_csv()读取数据,然后采用seaborn可视化部分数据来进行初步判断。
观察数据可知,变量包含’色泽’等8个属性,其中6个标称属性,2个连续属性。类标签为西瓜是否好瓜(两类):
下面是一些数据可视化图像:
下图是含糖率和密度两个连续变量的可视化图,这个图在之前的练习中也有出现:
下图则是更多的变量两两组合可视化图:
基于可视化手段进行一些分析,看以大概了解数据的分布及其与类别的关系。
编程实现ID3算法
在进行编程之前,先做一些分析如下:
- 对于树形结构,可以创建节点类来进行操作,根据书p74决策树基本算法,广泛采用递归操作;
- 对于连续属性(密度、含糖率),参考书p83,对其进行离散化(可采用二分法);
- 对于标称属性(色泽、纹理等),考虑Python字典,方便操作其特征类别(如:’色泽’ -> ‘青绿’,’乌黑’,’浅白’);
- 由于数据集完整,这里暂不考虑缺值问题(若需考虑,可参考书p86-87的加权思路 -> C4.5算法);
下面是实现过程:
建立决策树节点类
该节点类包含当前节点的属性,向下划分的属性取值,节点的类标签(叶节点有效,为通用性而保留所有节点类标签);
样例代码如下:
1 | ''' |
递归实现决策树生成算法主体
基本的决策树生成算法参照书p74-图4.2,如下所示:
下面是算法主体代码,注意对连续变量和离散变量的不同操作:
1 | def TreeGenerate(df): |
最优划分属性选择-信息增益判断
ID3算法采用信息增益最大化来实现最优划分属性的选择,这里主要的挑战是离散和连续两种属性变量的分别操作。对于离散变量(categoric variable),参考书p75-77内容实现,对于连续变量(continuous variable),采用书p83-85所介绍的二分法实现。
相关内容如信息熵、信息增益最大化、二分法等可参考书p75-76及p84页内容。
具体的实现代码:查看完整代码。
如下所示为综合了离散类别变量和连续变量的信息增益计算代码实现:
1 | ''' |
划分训练集和测试集生成模型
首先给出预测函数,采用简单的向下搜索即可实现。查看完整代码。
通过多次划分训练集和测试集,评估出所生成的完全决策树的预测精度,下面是几种不同情况下的结果和分析:
训练集为整个数据样本的情况:
accuracy: 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 average accuracy: 1.000
此时预测准度为100%,结果证明了题4-1。
采用pydotplus.graphviz绘图库,可以画出这样一棵完全决策树如下图(点击查看绘图程序):
训练集与测试集各取一半:
accuracy: 0.556 0.778 0.333 0.778 0.444 0.333 0.667 0.444 0.778 0.333 average accuracy: 0.544
多次实验预测准度均在55%左右(几乎等同于随机预测),说明此时模型无实用性。
按照K折交叉验证模型(k=5):
accuracy: 1.000 0.000 0.667 1.000 0.000 average accuracy: 0.533
结果精度依然很不理想,可以看到,不同的训练集与测试集的划分导致结果差别很大,这主要是由于数据量太少的缘故。
只分析离散属性:
accuracy: 1.000 0.000 0.333 0.667 0.000 average accuracy: 0.400
此时由于特征信息减少,模型更差了。
综上,为提高决策树泛化预测精度,需要进一步对其进行剪枝。
关于剪枝实现可参考下一题。
相关参考
1.seaborn/matplotlib可视化、中文字符处理:
- seaborn官网 - Plotting with categorical data
- seaborn显示中文 - The solution of display chinese in seaborn plot
- Linux下解决matplotlib中文乱码的方法
- Unicode和Python的中文处理
2.python基础知识:
3.决策树绘制相关: